/******************************************************************************
 * FileName:    gwin_global_data.h
 * Desc:        全局变量
 *
 *
 * Author:      Lin
 * Notes:
 *
 ******************************************************************************/

#ifndef __GWIN_GLOBAL_DATA_H__
#define __GWIN_GLOBAL_DATA_H__


/*-------------------------- Includes ---------------------------------------*/
#include "gwin_board.h"
#include "gwin_fifo.h"
#include "gwin_misc_api.h"
#include "gwin_general_clock.h"
#include "gwin_utc_clock.h"

#include "miio_user_api.h"


/*-------------------------- Macro Definitions ------------------------------*/
#define PRODUCT_MARK_SIZE               ( 64 - 8 )          // 产品标识符 长度
#define PRODUCT_MARK_NETWORK_RESET_AUTO ( 0 )               // 产品标识符不匹配自动重置网络（不匹配上电5秒会重置网络，客户生产先优化掉这5秒，暂时关掉这部分逻辑，后续真的不需要即删除 --- 240909）
#define DELAY_SPEC_SAVE                 ( 2 )               // 延时 保存spec
#define DELAY_REBOOT                    ( 2 )               // 延时 重启
#define DELAY_NETWORK_RESET             ( 2 )               // 延时 重置网络
#define LOW_PWR_TIME_SECOND             ( 5 )               // 唤醒时间
#define VERSION_LEN                     ( 4 )               // 版本号长度
#define BLE_MAC_ADDR_LEN                ( 6 )               // ble地址长度
#define BLE_NAME_MAX_LEN                ( 32 )              // ble蓝牙名称长度
#define BLE_ADV_TIMEOUT                 ( 30 * 60 * 1000 )  // ble广播超时 单位ms
#define BLE_ADV_INTERVAL                ( 1000 )            // ble广播间隔
#define BLE_ADV_INTERVAL_QUICK          ( 100 )             // ble广播间隔 快速
#define FORCE_UPLOAD_TIME_NETWORK       ( 2 )               // 一段时间参数后才上报数据 2秒 配网
#define MESH_REQUEST_INFO_TIME          ( 10 )              // mesh请求服务器信息 10秒
#define REMOTE_PAIR_CNT_MAX             ( 8 )               // 遥控最大配置个数
#define REMOTE_ID_LEN                   ( 4 )               // 遥控id长度
#define REMOTE_FILTER_CMD_CNT           ( 15 )              // 遥控过滤命令个数
#define SYS_UPLOAD_TIME                 ( 1 )               // 一段时间参数不变则上报 1秒
#define SYS_UPLOAD_PER_SECOND_CNT_MAX   ( 3 )               // 限制每秒钟最多上报条数，减少协议栈压栈压力
#define GWIN_SPEC_LEN_MAX               ( 32 )              // 最多存储8条spec属性
#define GWIN_SPEC_STR_LEN_MAX           ( 6 )               // 最多存储6条spec属性 字符串
#define GWIN_SPEC_STR_UNIT_LEN_MAX      ( 32 )              // spec属性字符串长度
#define SPEC_INDEX_MIOT_SECURITY_0      ( 0 )               // 米家加密
#define SPEC_INDEX_MIOT_SECURITY_1      ( 1 )               // 米家加密

#define SYSTEM_DEBUG(...)                       _GWIN_DEV_DEBUG(__VA_ARGS__)
#if (GWIN_DEBUG_EN)
#define USER_DEBUG(...)                         GWIN_DEV_DEBUG(__VA_ARGS__)
#define GWIN_OS_TIMER_ASSERT(timer)             if (NULL == (timer))                        \
                                                {                                           \
                                                    GWIN_DEBUG("timer create NULL!!!");     \
                                                    while(1);                               \
                                                }
#define PRINTK(fmt, ...)                        // printk(fmt"\r\n", ##__VA_ARGS__)
#else
#define USER_DEBUG(...)
#define GWIN_OS_TIMER_ASSERT(timer)
#define PRINTK(fmt, ...)
#endif


/*-------------------------- Type Declarations ------------------------------*/
/**
 * @brief 用户存储区id
 */
typedef enum
{
    RECORD_ID_PRODUCT_MARK,
    RECORD_ID_PRODUCT_CFG,
    RECORD_ID_NETWORK,
    RECORD_ID_SPEC,
    RECORD_ID_SPEC_2,                   // 操作flash接口一般大小是 uint8_t，spec结构体超了
    RECORD_ID_SPEC_STR,
    RECORD_ID_SPEC_STR_2,               // 操作flash接口一般大小是 uint8_t，spec结构体超了
}record_id_t;
#define RECORD_ID_MIN                   RECORD_ID_PRODUCT_CFG

/**
 * @brief 系统参数表
 */
typedef struct
{
    uint8_t size;                       // 长度
    uint8_t *memory_addr;               // 内存地址
    uint8_t *defalut_addr;              // 默认地址
}system_param_default_t;

/**
 * @brief 产品标识符
 */
typedef struct
{
    uint8_t model_name[PRODUCT_MARK_SIZE];
    uint32_t reserve1;                  // 保留
    uint32_t reserve2;                  // 保留
}product_mark_t;


/**
 * @brief 设置
 */
typedef struct
{
    uint8_t lock;                       // mesh设备，配网成功后锁定model、pid
    char model[BLE_NAME_MAX_LEN + 1];
    uint16_t pid;
    char version[VERSION_LEN + 1];
    uint16_t version_num                : 15;
    uint16_t version_custom_enable      : 1;    // 自定义版本使能，串口未修改，就认为不需要
    uint16_t miot_security_siid;
    uint32_t network_timeout;
    uint32_t reserve[4];
}system_param_product_t;

/**
 * @brief 数据类型
 */
typedef enum
{
    DATA_TYPE_BOOL      = 0x01,
    DATA_TYPE_U8        = 0x11,
    DATA_TYPE_U16       = 0x12,
    DATA_TYPE_U32       = 0x14,
    DATA_TYPE_U64       = 0x18,
    DATA_TYPE_I8        = 0x21,
    DATA_TYPE_I16       = 0x22,
    DATA_TYPE_I32       = 0x24,
    DATA_TYPE_I64       = 0x28,
    DATA_TYPE_F32       = 0x64,
    DATA_TYPE_STRING    = 0x70,
    DATA_TYPE_NONE      = 0xFF,         // 无用值，暂时用作返回值
}data_type_t;
#define GWIN_SPEC_PEA_IID_NONE          ( 0xFFFF )
#define GWIN_SPEC_UNIT_LEN              ( 11 )
#define GWIN_SPEC_STR_LEN(payload_len)  ( (payload_len) - 7 )

/**
 * @brief spec属性点
 */
typedef struct
{
    uint16_t siid;                      // 服务(service)
    uint16_t ea_iid;                    // 事件(event) 动作(action)
    uint16_t piid;                      // 属性(property)
    uint8_t change      : 1;            // 数据被修改，需要上报，上报成功清零
    uint8_t len         : 7;            // 字符串长度（如果是字符串类型）
    uint8_t data_type;                  // 数据类型，data_type_t
    uint32_t value;                     // 数据
}gwin_spec_unit_t;

/**
 * @brief spec
 */
typedef struct
{
    uint8_t len;
    uint8_t upload_total;               // 参数全部上报
    uint16_t reserve2;
    uint32_t reserve3;
    gwin_spec_unit_t data[GWIN_SPEC_LEN_MAX];
}gwin_spec_t;

/**
 * @brief spec字符串存储单元
 */
typedef struct
{
    char data[GWIN_SPEC_STR_UNIT_LEN_MAX + 1];
    uint8_t len;
    uint8_t used;
    uint8_t reserve;
}gwin_spec_str_unit_t;

/**
 * @brief spec字符串存储
 */
typedef struct
{
    uint8_t total_cnt;
    uint8_t reserve1;
    uint16_t reserve2;
    uint32_t reserve3;
    gwin_spec_str_unit_t str[GWIN_SPEC_STR_LEN_MAX];
}gwin_spec_str_t;

/**
 * @brief 系统状态
 */
typedef enum
{
    SYS_STATE_DISCONNECT,               // 断开连接
    SYS_STATE_CONNECT,                  // 连接
    SYS_STATE_WAIT_PAIR,                // 待配对
    SYS_STATE_FACTORY_TEST,             // 厂测
    SYS_STATE_LOW_PWR,                  // 低功耗
    SYS_STATE_NETWORK_PROVISIONED,      // 配网成功
    SYS_STATE_FACTORY_TEST_FAIL         = 0x10,     // 厂测失败
    SYS_STATE_FACTORY_TEST_SUCCESS      = 0x11,     // 厂测成功
    SYS_STATE_LOW_PWR_EXIT,             // 退出低功耗
    SYS_STATE_LOW_PWR_ENTER,            // 进入低功耗
    SYS_STATE_START                     = 0xCC,     // 启动完成
}sys_state_t;

/**
 * @brief 天气（来自小米官方文档）
 */
typedef enum
{
    SUNNY                       = 0,    // 晴
    LOUDY                       = 1,    // 多云
    VERCAST                     = 2,    // 阴
    HOWER                       = 3,    // 阵雨
    HUNDERSHOWER                = 4,    // 雷阵雨
    HUNDERSHOWER_WITH_HAIL      = 5,    // 雷阵雨伴有冰雹
    LEET                        = 6,    // 雨夹雪
    IGHT_RAIN                   = 7,    // 小雨
    ODERATE_RAIN                = 8,    // 中雨
    HEAVY_RAIN                  = 9,    // 大雨
    STORM                       = 10,   // 暴雨
    HEAVY_STORM                 = 11,   // 大暴雨
    SEVERE_STORM                = 12,   // 特大暴雨
    SNOW_FLURRY                 = 13,   // 阵雪
    LIGHT_SNOW                  = 14,   // 小雪
    MODERATE_SNOW               = 15,   // 中雪
    HEAVY_SNOW                  = 16,   // 大雪
    SNOWSTORM                   = 17,   // 暴雪
    FOGGY                       = 18,   // 雾
    ICE_RAIN                    = 19,   // 冻雨
    DUSTSTORM                   = 20,   // 沙尘暴
    LIGHT_TO_MODERATE_RAIN      = 21,   // 小到中雨
    MODERATE_TO_HEAVY_RAIN      = 22,   // 中到大雨
    HEAVY_RAIN_TO_STORM         = 23,   // 大到暴雨
    STORM_TO_HEAVY_STORM        = 24,   // 暴雨到大暴雨
    HEAVY_TO_SEVERE_STORM       = 25,   // 大暴雨到特大暴雨
    LIGHT_TO_MODERATE_SNOW      = 26,   // 小到中雪
    MODERATE_TO_HEAVY_SNOW      = 27,   // 中到大雪
    HEAVY_SNOW_TO_SNOWSTORM     = 28,   // 大到暴雪
    DUST                        = 29,   // 浮尘
    SAND                        = 30,   // 扬沙
    SANDSTORM                   = 31,   // 强沙尘暴
    DENSE_FOGGY                 = 32,   // 浓雾
    SNOW                        = 33,   // 雪
    HEAVY_DENSE_FOG             = 49,   // 强浓雾
    HAZE                        = 53,   // 霾
    MODERATE_HAZE               = 54,   // 中度霾
    SEVERE_HAZE                 = 55,   // 重度霾
    HAZARDOUS_HAZE              = 56,   // 严重霾
    HEAVY_FOG                   = 57,   // 大雾
    EXTRA_HEAVY_DENSE_FOG       = 58,   // 特强浓雾
    RAIN                        = 301,  // 雨
    UNKNOWN                     = 99,   // 无
}gwin_weather_t;


/**
 * @brief 遥控对码
 */
typedef struct
{
    uint8_t remote_index        : 6;    // 查找到的遥控index
    uint8_t remote_exist        : 1;    // 是否查找到遥控index
    uint8_t groud_exist         : 1;    // 是否查找到遥控分组
}remote_pair_find_t;

/**
 * @brief 遥控对码
 */
typedef struct
{
    uint8_t remote_id[REMOTE_ID_LEN];   // 遥控编号
    uint16_t group_id;                  // 分组编号
    union
    {
        uint8_t reserve1;               // 保留
        uint8_t cmd_id;                 // 命令id
        remote_pair_find_t find;        // 查找状态
    };
    uint8_t used                : 1;    // 有用
    uint8_t group_mode          : 1;    // 分组模式，0：多分组，按位操作；1：单分组，直接记录
    uint8_t no_delete           : 1;    // 只对码，不清码
    uint8_t no_match_group      : 1;    // 不需要匹配分组号
    uint8_t from_le_shi         : 1;    // 乐式特殊化
}remote_pair_info_t;

/**
 * @brief 遥控过滤
 *          处理过的命令过滤
 */
typedef struct
{
    uint8_t remote_id[REMOTE_ID_LEN];       // 遥控编号
    uint8_t cmd_id[REMOTE_FILTER_CMD_CNT];  // 命令id
    uint8_t cmd_cnt;                        // 命令个数
    uint32_t hold_clock;                    // 持续时间
}remote_filter_map_t;

/**
 * @brief 遥控对码
 */
typedef struct
{
    remote_pair_info_t data[REMOTE_PAIR_CNT_MAX];   // 遥控对码
    uint8_t len;                                    // 长度
    uint8_t reserve1;                   // 保留
    uint16_t reserve2;                  // 保留
}remote_driver_public_t;


// 小米代码，暂时放这里
typedef struct
{
    uint8_t major;
    uint8_t minor;
    uint8_t revision;
    uint8_t padding;
    uint16_t developer_version;

    uint16_t p;
    const uint8_t *m;

    uint32_t magic;
} info_t;


/**
 * @brief 广云产品信息包
 */
#define GWIN_COMPANY_ID_DEV_PAIR_INFO           0x0DD8      // 厂商ID
#pragma pack(1)
typedef struct
{
    uint8_t ble_adv_len;                        // 蓝牙广播数据格式 长度
    uint8_t ble_adv_type;                       // 蓝牙广播数据格式 类型

    uint16_t company_id;                        // 厂商ID（2Byte）
    uint16_t pid;                               // 产品短PID（2Byte）
    uint8_t mac_addr[6];                        // mac地址（6Byte）
    uint8_t product_type;                       // 产品类型（1Byte）
    uint8_t qrcode[16];                         // 二维码（16Byte）
}dev_pair_info_t;
#pragma pack()

/**
 * @brief 系统参数
 */
typedef struct
{
    system_param_product_t product;             // 设置
    uint32_t network_provisioned;               // 配网状态
    gwin_spec_t spec;                           // 属性点，MCU发过来的属性点，都要存储，以防后台直接get，get的时候找MCU拿值会很慢
    gwin_spec_str_t spec_str;                   // 属性点，字符串缓存

    uint8_t delay_spec_save;                    // 延时 保存spec
    uint8_t delay_spec_str_save;                // 延时 保存spec str
    uint8_t delay_reboot;                       // 延时 重启
    uint8_t delay_network_reset;                // 延时 重置网络
    uint8_t delay_factory;                      // 延时 工厂测试
    uint8_t active_pair_time;                   // 激活配对
    uint8_t system_upload_force_wait;           // 系统参数强制延时，配网、蓝牙直连初期，系统参数强制延时，马上上报可能死机
    uint8_t mac_addr[BLE_MAC_ADDR_LEN];         // 蓝牙MAC地址
    uint8_t low_pwr_ctrl_second;                // 低功耗 倒计时
    uint16_t ble_adv_interval;                  // 广播间隔
    uint32_t network_timeout;                   // 配网超时
    int8_t timezone;                            // 时区，正：东；负：西，单位：时（没有分度）
    uint8_t sys_state;                          // 系统状态 sys_state_t
    uint8_t sys_state_extern;                   // 系统状态 发给外部模块 sys_state_t
    uint16_t weather;                           // 天气 gwin_weather_t
    uint32_t second;                            // 上电计秒

    uint32_t system_upload_clock[GWIN_SPEC_LEN_MAX];    // 系统参数上报时钟

    uint32_t miot_security[2];          // 米家照明开关加密算法

    // 一些标志位
    union
    {
        struct
        {
            uint8_t reset_all_force             : 1;    // 强制复位所有参数（后续可能删除，请看 PRODUCT_MARK_NETWORK_RESET_AUTO）
            uint8_t network_state               : 1;    // 连网状态，0：协议栈未初始化；1：协议栈已初始化，网络协议栈未初始调用协议栈API导致死机（这里不代表已经连上网关！！！！！）
            uint8_t utc_time_valid              : 1;    // utc时间有效
            uint8_t gatt_state                  : 1;    // 蓝牙直连状态
            uint8_t ota_state                   : 1;    // ota
            uint8_t factory_enter_disable       : 1;    // 厂测入口关闭
            uint8_t factory_test                : 1;    // 工厂测试
            uint8_t reboot                      : 1;    // 重启
            uint8_t network_reset               : 1;    // 重新配网
            uint8_t func_start                  : 1;    // 等待授权参数后，开始正式功能
            uint8_t keep_alive_init             : 1;    // 通用模板要手动保活 MI_MESH_TEMPLATE_CLOUD
        };
        uint32_t flag_total;
    };
}system_param_t;


/*-------------------------- Global Variables -------------------------------*/

/*-------------------------- Local Variables --------------------------------*/

/*-------------------------- Functions Declarations -------------------------*/

/*-------------------------- Functions Definitions --------------------------*/
void gwin_custom_record_check(void);
void gwin_custom_record_load(void);
void gwin_custom_record_save(uint16_t record_id);
void gwin_custom_record_reset(uint16_t record_id);
void gwin_custom_record_reset_all(void);

void gwin_custom_record_reset_all_force_force(void);

void gwin_custom_system_param_init_after_ble(void);


#endif // __GWIN_GLOBAL_DATA_H__


/*-------------------------- END OF FILE ------------------------------------*/

